﻿#pragma once

_NAMESPACE_BEGIN

///组件,实现运行时组装的设计模式
//每个组件只做简单的功能，可以最为插头插入其他的组件，同时可以最为插线板接受若干插头的接入，通过运行时临时拼接构成一个大的聚合体

class Panel
{
public:
	Panel();
	virtual ~Panel();
	virtual void Initial(){};///初始化
	virtual void Update();///更新函数
	virtual void Release(){/*Panel* p=this;SAFEDELETE(p);*/}///释放

	///组件的名称
	/*由于聚合体对象的部件都是临时拼成，给每个部件一个名称,可以动态查询连接上的插头,
	考虑到继承后的物体需要兼容父类，可以使用"base\derive"的形式
	*/
	string panel_name;
	string panel_description;///便于调试的描述信息
	///将本组件插入到上级组件
	/*上级组件
	*/
	virtual void PlugTo(Panel* parent);
	virtual void OnParentAddTo(){}//当上级组件添加到其他物体时触发
	virtual void OnParentRemove(){}//OnParentAddTo的反向操作
	///安静模式，将本组件插入上级组件
	/**上级组件更新时不通知本组件更新
	*/
	virtual void PlugToSilent(Panel* parent);
	Panel* FindPlugin(CONST_REF(string) name);//通过名称查找一个组件
	Panel* GetParent(){return panel_pParent;}//得到上级组件
	virtual void AddNeedUpdatePlugin(Panel& p);//添加需要通知更新的子组件
	std::vector<Panel*>& GetPlugins(){return plugins;}
	Panel* panel_pParent;///上级组件

protected:
	virtual void RecievePlug(Panel& p);///插入子组件
	void UpdatePlugins();///更新所有子组件

	std::vector<Panel*> plugins;///依附的子组件
	std::vector<Panel*> needUpdatePlugins;///需要随着本panel一起更新的组件

private:
};

///含有子物体的panel，一般来说子物体应该和本物体同类
class ParentPanel:public Panel
{
public:
	virtual ~ParentPanel();
	void Update();
	///添加子物体，注意这和子组件不同
	virtual void AddSon(Panel* p);
	virtual void RemoveSon(Panel* p);
	///得到子物体列表
	std::vector<Panel*>& GetSons(){return panel_sons;}
protected:
	///通知子物体更新
	virtual void UpdateSons();
	std::vector<Panel*> panel_sons;///<子物体，不是本聚合体的构成部分
private:
};

_NAMESPACE_END